import { ReactNode, useCallback, useEffect, useRef, useState } from "react"
import Link from "./Components/Link"
import Swiper from "./Components/Swiper"
import Toast from "./Components/Toast"
import { acfunList, list, yueduList } from "./constant"
import "./Mobile.less"

export default function Mobile() {
    const [title, setTitle] = useState("")

    const [content, setContent] = useState<string | ReactNode>("")

    const [showToast, setShowToast] = useState(false)

    const cancelToast = () => setShowToast(false)

    const confirmToastRef = useRef<(() => any) | undefined>(undefined)

    const [showToolbar, setShowToolbar] = useState(false)

    const wrapper = useRef<HTMLDivElement>(null)

    const yuedu = useRef<HTMLDivElement>(null)

    const acfun = useRef<HTMLDivElement>(null)

    const lolalytics = useRef<HTMLDivElement>(null)

    const [now, setNow] = useState("")

    const scroll: React.UIEventHandler<HTMLDivElement> = useCallback(e => {
        const yueduTop = yuedu.current!.offsetTop
        const acfunTop = acfun.current!.offsetTop
        const lolalyticsTop = lolalytics.current!.offsetTop
        const { scrollTop } = e.target as HTMLDivElement
        setShowToolbar(scrollTop > yueduTop - 2)
        if (scrollTop >= lolalyticsTop - 2) {
            setNow("lolalytics")
            return
        }
        if (scrollTop >= acfunTop - 2) {
            setNow("acfun")
            return
        }
        if (scrollTop >= yueduTop - 2) {
            setNow("yuedu")
            return
        }
        setNow("")
    }, [])

    const scrollToTop = useCallback(() => {
        wrapper.current!.scrollTo({
            top: 0,
            behavior: "smooth"
        })
    }, [])

    const scrollToYuedu = useCallback(() => {
        wrapper.current!.scrollTo({
            top: yuedu.current!.offsetTop,
            behavior: "smooth"
        })
    }, [])

    const scrollToAcfun = useCallback(() => {
        wrapper.current!.scrollTo({
            top: acfun.current!.offsetTop,
            behavior: "smooth"
        })
    }, [])

    const scrollToLolalytics = useCallback(() => {
        wrapper.current!.scrollTo({
            top: lolalytics.current!.offsetTop,
            behavior: "smooth"
        })
    }, [])

    const [showAllTool, setShowAllTool] = useState(false)

    useEffect(() => {
        if (showAllTool) {
            const timer = setTimeout(() => {
                setShowAllTool(false)
            }, 3000)
            return () => {
                clearTimeout(timer)
            }
        }
    }, [showAllTool])

    const [showMenu, setShowMenu] = useState(false)

    return (
        <div className="mobile" ref={wrapper} onScroll={scroll}>
            <Toast title={title} content={content} showToast={showToast} onCancel={cancelToast} onConfirm={confirmToastRef.current} />
            <div className="m-toolbar-wrapper" style={{ opacity: showAllTool ? 1 : 0.8, height: showAllTool ? "52.037037vw" : "9.259260vw" }}>
                <div className="m-toolbar" style={{ display: showToolbar ? "flex" : "none" }}>
                    <div className="m-go-item" style={{ backgroundImage: "url(/top.png)" }} onClick={showAllTool ? scrollToTop : () => setShowAllTool(true)}></div>
                    <div
                        className="m-go-item"
                        style={{
                            backgroundImage: "url(/yuedu.png)",
                            filter: `grayscale(${now === "yuedu" ? 0 : 1})`
                        }}
                        onClick={scrollToYuedu}></div>
                    <div
                        className="m-go-item m-acfun"
                        style={{
                            backgroundImage: "url(/acfun-icon.webp)",
                            filter: `grayscale(${now === "acfun" ? 0 : 1})`
                        }}
                        onClick={scrollToAcfun}></div>
                    <div
                        className="m-go-item"
                        style={{
                            backgroundImage: "url(/lolalytics.png)",
                            filter: `grayscale(${now === "lolalytics" ? 0 : 1})`
                        }}
                        onClick={scrollToLolalytics}></div>
                </div>
            </div>
            <div className="m-meun" style={{ left: showMenu ? 0 : "100vw" }}>
                <img src="/close.svg" alt="关闭" className="m-close-meun" onClick={() => setShowMenu(false)} />
                <Link href={list.github} className="m-meun-item" left={false} right={false}>
                    Github
                </Link>
                <div
                    className="m-meun-item"
                    onClick={() => {
                        setShowMenu(false)
                        scrollToYuedu()
                    }}>
                    Yuedu
                </div>
                <div
                    className="m-meun-item"
                    onClick={() => {
                        setShowMenu(false)
                        scrollToAcfun()
                    }}>
                    AcFun TV
                </div>
                <div
                    className="m-meun-item"
                    onClick={() => {
                        setShowMenu(false)
                        scrollToLolalytics()
                    }}>
                    LOLAlytics
                </div>
            </div>
            <div className="m-head">
                <div className="m-logo">
                    <img alt="logo" src="/logo.webp" />
                    <div className="m-name">陆荣 · 前端</div>
                </div>
                <img src="/hamburger.svg" alt="" className="m-hamburger" onClick={() => setShowMenu(true)} />
            </div>
            <div className="m-top">
                <div className="m-top-cover-wrapper">
                    <img src="/logo.webp" className="m-top-cover" alt="logo" />
                </div>
                <div className="m-top-intrd">
                    <p>你好，我叫陆荣</p>
                    <p>
                        毕业于
                        <Link href={list.nku} right={false}>
                            南开大学
                        </Link>
                        ，热爱
                    </p>
                    <p>
                        <Link left={false} right={false} href={list.js}>
                            JavaScript
                        </Link>
                        、
                        <Link href={list.react} left={false} right={false}>
                            React
                        </Link>
                    </p>
                    <p>
                        以及<Link href={list.ts}>TypeScript</Link>
                    </p>
                </div>
            </div>
            <div className="m-line"></div>
            <div className="m-project" ref={yuedu}>
                <div className="m-project-head">
                    <div className="m-project-name">
                        <div className="m-main-name m-yuedu">仙人掌阅读</div>
                        <div className="m-sub-name">综合性的新闻网站，包含前台、后台以及后端</div>
                    </div>
                    <div className="m-project-content">
                        <div className="m-project-text">想要尝试把自己已学的大部分技术融合出来，做一个综合性的项目，于是便做了这么一个包含了前台、后台以及后端的新闻网站</div>
                        <div
                            onClick={() => {
                                setShowToast(true)
                                setTitle("打开网站")
                                setContent("目标网站为 PC 端适配，是否跳转？")
                                confirmToastRef.current = () => {
                                    setShowToast(false)
                                    window.open(list.yuedu, "_blank")
                                }
                            }}
                            className="m-project-view">
                            <img className="m-view-icon" src="/web.svg" />
                            <div className="m-project-link">查看项目</div>
                            <img className="m-arrow-right" src="/arrow-right.png" />
                        </div>
                    </div>
                </div>
                <div className="m-project-swiper">
                    <Swiper data={yueduList} width={81.481481} height={45.833333} border={1.111111} unit="vw" interval={5000} bottomHeight={9.259259} dotWidth={3.703704} dotBorder={0.37037} dotMargin={1.388889} />
                </div>
                <div className="m-project-result">
                    <div className="m-result-title">项目总结：</div>
                    <div className="m-result-content">
                        <p>
                            前台技术栈：
                            <Link href={list.ts} left={false}>
                                TypeScript
                            </Link>
                            +<Link href={list.react}>React</Link>+<Link href={list.tvos}>React Router</Link>+<Link href={list.axios}>Axios</Link>+<Link href={list.mobx}>MobX</Link>+<Link href={list.antd}>Ant Design</Link>
                        </p>
                        <p>
                            后台技术栈：
                            <Link href={list.ts} left={false}>
                                TypeScript
                            </Link>
                            +<Link href={list.umi}>Umi</Link>+<Link href={list.antd}>Ant Design</Link>+<Link href={list.antv}>Ant Design Charts</Link>+<Link href={list.wang}>WangEditor</Link>
                        </p>
                        <p>
                            后端技术栈：
                            <Link href={list.ts} left={false}>
                                Node
                            </Link>
                            +<Link href={list.ts}>TypeScript</Link>+<Link href={list.express}>Express</Link>+<Link href={list.mysql}>MySQL</Link>+<Link href={list.jwt}>JSON Web Token</Link>
                        </p>
                        <p>前后端分离的通点在于接口类型，由于都是使用 TypeScript 进行开发，所以可以共享一套 d.ts 文件实现类型通用</p>
                        <p>前端对 Axios 和 UmiRequest 分别进行了二次封装，能够自动识别出接口返回的 TypeScript 类型</p>
                        <p>后端对 Express 进行了二次封装，约束接口必须发送符合类型的数据</p>
                        <p>
                            在写项目过程中，为了解决出现的问题和需求写了两个
                            <Link href={list.npm}>
                                <img src="/npm.png" alt="NPM" className="m-npm" />
                                NPM 库
                            </Link>
                        </p>
                        <p className="m-no-dot">
                            —<Link href={list.html2jsx}>Convert-HTML-To-JSX</Link>
                            ，将 HTML 代码转换为自定义组件，比如 Ant Design 或者 React Native 中的组件
                        </p>
                        <p className="m-no-dot">
                            —<Link href={list.easymysqltools}>Easy-MySQL-Tools</Link>
                            ，基于 MySQL2 进行二次封装，能够自动识别数据库操作的类型，并可以对查询配置进行代码提示
                        </p>
                    </div>
                </div>
            </div>
            <div className="m-line"></div>
            <div className="m-project" ref={acfun}>
                <div className="m-project-head">
                    <div className="m-project-name">
                        <div className="m-main-name m-acfun">AcFun TV</div>
                        <div className="m-sub-name">知名弹幕网站 AcFun 的 Android TV 版本 APP</div>
                    </div>
                    <div className="m-project-content">
                        <div className="m-project-text">
                            <Link href={list.acfun} left={false}>
                                AcFun 弹幕视频网
                            </Link>
                            并无 TV 版，于是利用{" "}
                            <Link href={list.rn} left={false}>
                                React Native
                            </Link>
                            开发了一个 Android TV 版本APP，支持遥控，视频播放、弹幕等功能
                        </div>
                        <Link href={list.actv} className="m-project-view">
                            <img className="m-view-icon" src="/github.png" />
                            <div className="m-project-link">查看项目</div>
                            <img className="m-arrow-right" src="/arrow-right.png" />
                        </Link>
                    </div>
                </div>
                <div className="m-project-swiper">
                    <Swiper data={acfunList} width={81.481481} height={45.833333} border={1.111111} unit="vw" interval={5000} bottomHeight={9.259259} dotWidth={3.703704} dotBorder={0.37037} dotMargin={1.388889} />
                </div>
                <div className="m-project-result">
                    <div className="m-result-title">项目总结：</div>
                    <div className="m-result-content">
                        <p>
                            技术栈：
                            <Link href={list.tvos} left={false}>
                                React Native TVOS
                            </Link>
                            +<Link href={list.tvos}>React Navigation</Link>+<Link href={list.tvos}>React Native Video</Link>+<Link href={list.tvos}>React Native Webview</Link>+<Link href={list.mobx}>MobX</Link>
                        </p>
                        <p>国内的 React Native 知识基本全部过时，用来开发 Android TV 的相关信息更是几乎为零，遇到问题只能自己不断地调试，以及在 Google 或者 StackOverflow 上搜索</p>
                        <p>遇到一个电视设备无法正确被识别为 TV 的问题，反复调试无法解决，最终修改了 React Native 源码中的一个方法，成功解决</p>
                        <p>
                            React Native 中没有可用的弹幕库，自己尝试利用 React Native 的原生动画 API 编写了
                            <Link href={list.danmu} left={false}>
                                React-Native-Danmaku-Player
                            </Link>
                            ，显示效果和性能都很好
                        </p>
                        <p>
                            <Link href={list.acvideo} left={false}>
                                相关视频
                            </Link>
                            在 AcFun 获得极高关注，<b>占据热度以及播放排行榜第一长达一个多月</b>
                        </p>
                    </div>
                </div>
            </div>
            <div className="m-line"></div>
            <div className="m-project" ref={lolalytics}>
                <div className="m-project-head">
                    <div className="m-project-name">
                        <div className="m-main-name m-lolalytics">乱斗宝典</div>
                        <div className="m-sub-name">知名数据网站 lolalytics 的小程序版本</div>
                    </div>
                    <div className="m-project-content">
                        <div className="m-project-text">
                            <a href="https://lolalytics.com/lol/tierlist/" target="_blank" rel="noreferrer">
                                LOLAlytics
                            </a>
                            &nbsp;数据网站在国内访问较慢，部分的确甚至无法访问，于是开发了微信小程序的版本，数据每天自动同步更新
                        </div>
                        <div
                            onClick={() => {
                                setShowToast(true)
                                setTitle("打开微信小程序")
                                setContent(
                                    <span>
                                        由于微信官方禁止个人认证的小程序从网页进行跳转，您可以点击“前往”跳转到微信后，手动搜索小程序“<b>乱斗助手</b>”
                                    </span>
                                )
                                confirmToastRef.current = () => {
                                    setShowToast(false)
                                    window.open(list.lolalytics, "_blank")
                                }
                            }}
                            className="m-project-view">
                            <img className="m-view-icon" src="/mini-app.png" />
                            <div className="m-project-link">查看项目</div>
                            <img className="m-arrow-right" src="/arrow-right.png" />
                        </div>
                    </div>
                </div>
                <div className="m-mobile-list">
                    <div className="m-phone-wrapper">
                        <img className="m-phone-screen" src="/phone_0.webp" />
                    </div>
                    <div className="m-phone-wrapper">
                        <img className="m-phone-screen" src="/phone_1.webp" />
                    </div>
                    <div className="m-phone-wrapper">
                        <img className="m-phone-screen" src="/phone_2.webp" />
                    </div>
                </div>
                <div className="m-project-result">
                    <div className="m-result-title">项目总结：</div>
                    <div className="m-result-content">
                        <p>
                            技术栈：
                            <Link href={list.ts} left={false}>
                                TypeScript
                            </Link>
                            +<Link href={list.taro}>Taro</Link>+<Link href={list.wxcloud}>Serverless</Link>+<Link href={list.puppeteer}>Puppeteer</Link>
                        </p>
                        <p>Taro 的部分 API 与微信小程序不一致</p>
                        <p>使用虚拟列表解决了子元素过多时加载白屏和滚动卡顿的问题</p>
                        <p>
                            原网站的数据加密，使用
                            <Link href={list.puppeteer}>Puppeteer</Link>
                            无头浏览器进行爬取数据，同步更新
                        </p>
                        <p>累计用户近 300 余人</p>
                    </div>
                </div>
            </div>
            <div className="m-line"></div>
            <div className="m-contact">
                <div className="m-contact-title">联系 · 我</div>
                <div className="m-contact-list">
                    <a href="https://github.com/1adybug" target="_blank" rel="noreferrer" className="m-contact-link">
                        <img className="m-contact-icon" src="/github.png" />
                        <div className="m-contact-type">Github</div>
                    </a>
                    <a href="mailto:lurongv@qq.com" target="_blank" rel="noreferrer" className="m-contact-link">
                        <img className="m-contact-icon" src="/mail.png" />
                        <div className="m-contact-type">Email</div>
                    </a>
                </div>
            </div>
        </div>
    )
}
